﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;

namespace Assets
{
    internal class Square
    {
        public readonly Vector2 position;
        float gridScale;

        Vector2 tR;
        Vector2 bR;
        Vector2 bL;
        Vector2 tL;

        Vector2 tC;
        Vector2 bC;
        Vector2 lC;
        Vector2 rC;

        public readonly List<Vector3> vertices = new List<Vector3>();
        public readonly List<ushort> triangles = new List<ushort>();

        public Square(Vector2 position, float gridScale)
        {
            this.position = position;
            this.gridScale = gridScale;
            tR = Vector2.one / 2 * gridScale;
            bR = Vector2.down * gridScale + tR;
            bL = Vector2.left * gridScale + bR;
            tL = Vector2.up * gridScale + bL;

            tC = (tR - tL) / 2 + tL;
            bC = (bR - bL) / 2 + bL;
            lC = (tL - bL) / 2 + bL;
            rC = (tR - bR) / 2 + bR;
        }
        public void Tr(float isoValue, float tLeftValue, float topRightValue, float bLeftValue, float bRightValue)
        {
            vertices.Clear();
            triangles.Clear();
            Inter(isoValue, tLeftValue, topRightValue, bLeftValue, bRightValue);
            Tr(Getstate(isoValue, tLeftValue, topRightValue, bLeftValue, bRightValue));
        }
        void Inter(float isoValue, float tLeftValue, float topRightValue, float bLeftValue, float bRightValue)
        {
            tC = IN(tLeftValue, topRightValue, isoValue, tL, tR);
            rC = IN(topRightValue, bRightValue, isoValue, tR, bR);
            bC = IN(bLeftValue, bRightValue, isoValue, bL, bR);
            lC = IN(tLeftValue, bLeftValue, isoValue, tL, bL);
            static Vector2 IN(float x, float y, float v, Vector2 x2, Vector2 y2)
            {
                float lerp = Mathf.InverseLerp(x, y, v);
                lerp = Mathf.Clamp01(lerp);
                Vector2 point = x2 + (y2 - x2) * lerp;
                return point;
            }
        }
        [Flags]
        enum PointState
        {
            None = 0,
            TR = 1 << 0,
            BR = 1 << 1,
            BL = 1 << 2,
            TL = 1 << 3,
        }
        PointState Getstate(float isoValue, float tLeftValue, float topRightValue, float bLeftValue, float bRightValue)
        {
            PointState pointState = PointState.None;
            if (topRightValue > isoValue)
                pointState |= PointState.TR;
            if (tLeftValue > isoValue)
                pointState |= PointState.TL;
            if (bRightValue > isoValue)
                pointState |= PointState.BR;
            if (bLeftValue > isoValue)
                pointState |= PointState.BL;
            return pointState;
        }
        void Tr(PointState pointState)
        {
            switch (pointState)
            {
                case 0:
                    break;
                case PointState.TR:
                    vertices.Add(tR);
                    vertices.Add(rC);
                    vertices.Add(tC);
                    triangles.Add(0);
                    triangles.Add(1);
                    triangles.Add(2);
                    break;
                case PointState.BR:
                    vertices.Add(rC);
                    vertices.Add(bR);
                    vertices.Add(bC);
                    triangles.Add(0);
                    triangles.Add(1);
                    triangles.Add(2);
                    break;
                case PointState.BL:
                    vertices.Add(bC);
                    vertices.Add(bL);
                    vertices.Add(lC);
                    triangles.Add(0);
                    triangles.Add(1);
                    triangles.Add(2);
                    break;
                case PointState.TL:
                    vertices.Add(tL);
                    vertices.Add(tC);
                    vertices.Add(lC);
                    triangles.Add(0);
                    triangles.Add(1);
                    triangles.Add(2);
                    break;
                case PointState.BR | PointState.TR:
                    vertices.Add(tR);
                    vertices.Add(bR);
                    vertices.Add(bC);
                    vertices.Add(tC);
                    triangles.Add(0);
                    triangles.Add(1);
                    triangles.Add(2);
                    triangles.Add(0);
                    triangles.Add(2);
                    triangles.Add(3);
                    break;

                case PointState.TR | PointState.BL:
                    vertices.Add(tR);
                    vertices.Add(rC);
                    vertices.Add(bC);
                    vertices.Add(bL);
                    vertices.Add(lC);
                    vertices.Add(tC);
                    triangles.Add(0);
                    triangles.Add(1);
                    triangles.Add(2);
                    triangles.Add(0);
                    triangles.Add(2);
                    triangles.Add(3);
                    triangles.Add(0);
                    triangles.Add(3);
                    triangles.Add(4);
                    triangles.Add(0);
                    triangles.Add(4);
                    triangles.Add(5);
                    break;
                case PointState.BL | PointState.BR:
                    vertices.Add(bR);
                    vertices.Add(bL);
                    vertices.Add(lC);
                    vertices.Add(rC);
                    triangles.Add(0);
                    triangles.Add(1);
                    triangles.Add(2);
                    triangles.Add(0);
                    triangles.Add(2);
                    triangles.Add(3);
                    break;
                case PointState.BL | PointState.BR | PointState.TR:
                    vertices.Add(tR);
                    vertices.Add(bR);
                    vertices.Add(bL);
                    vertices.Add(lC);
                    vertices.Add(tC);
                    triangles.Add(0);
                    triangles.Add(1);
                    triangles.Add(2);
                    triangles.Add(0);
                    triangles.Add(2);
                    triangles.Add(3);
                    triangles.Add(0);
                    triangles.Add(3);
                    triangles.Add(4);
                    break;
                case PointState.TL | PointState.TR:
                    vertices.Add(tR);
                    vertices.Add(rC);
                    vertices.Add(lC);
                    vertices.Add(tL);
                    triangles.Add(0);
                    triangles.Add(1);
                    triangles.Add(2);
                    triangles.Add(0);
                    triangles.Add(2);
                    triangles.Add(3);
                    break;
                case PointState.BR | PointState.TL:
                    vertices.Add(rC);
                    vertices.Add(bR);
                    vertices.Add(bC);
                    vertices.Add(lC);
                    vertices.Add(tL);
                    vertices.Add(tC);
                    triangles.Add(0);
                    triangles.Add(1);
                    triangles.Add(2);
                    triangles.Add(0);
                    triangles.Add(2);
                    triangles.Add(3);
                    triangles.Add(0);
                    triangles.Add(3);
                    triangles.Add(4);
                    triangles.Add(0);
                    triangles.Add(4);
                    triangles.Add(5);
                    break;
                case PointState.BR | PointState.TR | PointState.TL:
                    vertices.Add(tR);
                    vertices.Add(bR);
                    vertices.Add(bC);
                    vertices.Add(lC);
                    vertices.Add(tL);
                    triangles.Add(0);
                    triangles.Add(1);
                    triangles.Add(2);
                    triangles.Add(0);
                    triangles.Add(2);
                    triangles.Add(3);
                    triangles.Add(0);
                    triangles.Add(3);
                    triangles.Add(4);
                    break;
                case PointState.TL | PointState.BL:
                    vertices.Add(bC);
                    vertices.Add(bL);
                    vertices.Add(tL);
                    vertices.Add(tC);
                    triangles.Add(0);
                    triangles.Add(1);
                    triangles.Add(2);
                    triangles.Add(0);
                    triangles.Add(2);
                    triangles.Add(3);
                    break;
                case PointState.BL | PointState.TR | PointState.TL:
                    vertices.Add(tR);
                    vertices.Add(rC);
                    vertices.Add(bC);
                    vertices.Add(bL);
                    vertices.Add(tL);
                    triangles.Add(0);
                    triangles.Add(1);
                    triangles.Add(2);
                    triangles.Add(0);
                    triangles.Add(2);
                    triangles.Add(3);
                    triangles.Add(0);
                    triangles.Add(3);
                    triangles.Add(4);
                    break;
                case PointState.BL | PointState.BR | PointState.TL:
                    vertices.Add(rC);
                    vertices.Add(bR);
                    vertices.Add(bL);
                    vertices.Add(tL);
                    vertices.Add(tC);
                    triangles.Add(0);
                    triangles.Add(1);
                    triangles.Add(2);
                    triangles.Add(0);
                    triangles.Add(2);
                    triangles.Add(3);
                    triangles.Add(0);
                    triangles.Add(3);
                    triangles.Add(4);
                    break;
                case (PointState.BL | PointState.BR | PointState.TL | PointState.TR):
                case (PointState)(-1):
                    vertices.Add(tR);
                    vertices.Add(bR);
                    vertices.Add(bL);
                    vertices.Add(tL);
                    triangles.Add(0);
                    triangles.Add(1);
                    triangles.Add(2);
                    triangles.Add(0);
                    triangles.Add(2);
                    triangles.Add(3);
                    break;
                default:
                    Debug.LogWarning((int)pointState + "无符合项");
                    break;
            }
        }
    }
}
